﻿using System;
using System.Runtime.InteropServices;

namespace LSA.Framework.Pinvoke
{
    public static unsafe class CppInvoker
    {
        private const string Path = @"LSA.Svd.dll";

        [DllImport(Path, EntryPoint = "svdNewSMat", CallingConvention = CallingConvention.Cdecl)]
        public static extern SparseMatrix* BuildNewSparseMatrix(int rows, int cols, int vals);

        [DllImport(Path, EntryPoint = "svdNewDMat", CallingConvention = CallingConvention.Cdecl)]
        public static extern DenseMatrix* BuildNewDenseMatrix(int rows, int cols);

        [DllImport(Path, EntryPoint = "svdLAS2A", CallingConvention = CallingConvention.Cdecl)]
        public static extern SvdResult* PerformSvd(SparseMatrix* a, int dimensions);

        [DllImport(Path, EntryPoint = "svdTransposeD", CallingConvention = CallingConvention.Cdecl)]
        public static extern DenseMatrix* TransposeDenseMatrix(DenseMatrix* matrix);

        [DllImport(Path, EntryPoint = "svdTransposeD", CallingConvention = CallingConvention.Cdecl)]
        public static extern DenseMatrix* TransposeDenseMatrix(IntPtr matrix);

        [DllImport(Path, EntryPoint = "svdTransposeSD", CallingConvention = CallingConvention.Cdecl)]
        public static extern void TransposeDenseMatrix(double** matrix, int rows, int cols);

        /// <summary>
        /// Multiplies two matrices.
        /// </summary>
        /// <param name="n">Matrix A`s number of rows</param>
        /// <param name="m">Matrix A`s number of cols as well as Matrix B`s number of rows</param>
        /// <param name="p">Matrix B`s number of cols</param>
        /// <param name="a">Matrix A</param>
        /// <param name="b">Matrix B</param>
        /// <param name="c">Resulting matrix</param>
        [DllImport(Path, EntryPoint = "matMult", CallingConvention = CallingConvention.Cdecl)]
        public static extern void MatrixMultiplication(int n, int m, int p, double** a, double** b, double** c);

        [DllImport(Path, EntryPoint = "createNewArray", CallingConvention = CallingConvention.Cdecl)]
        public static extern double** CreateNewArray(int rows, int cols);

        [DllImport(Path, EntryPoint = "createNew1Array", CallingConvention = CallingConvention.Cdecl)]
        public static extern int* CreateNew1dArray(int cols);

        [DllImport(Path, EntryPoint = "kMeans", CallingConvention = CallingConvention.Cdecl)]
        public static extern double** KMeans(double** data, int n, int d, int k, int* clusters);
    }
}
